package com.baoteng.rbspy.config;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;

import javax.annotation.PostConstruct;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.mustache.MustacheEnvironmentCollector;
import org.springframework.boot.autoconfigure.mustache.MustacheResourceTemplateLoader;
import org.springframework.boot.autoconfigure.template.AbstractTemplateViewResolverProperties;
import org.springframework.boot.autoconfigure.template.TemplateLocation;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;

import com.baoteng.rbspy.model.DateTime;
import com.baoteng.rbspy.util.BaseUtil;
import com.samskivert.mustache.Mustache;
import com.samskivert.mustache.Mustache.Collector;
import com.samskivert.mustache.Mustache.TemplateLoader;

@Configuration
@ConditionalOnClass(Mustache.class)
@ConfigurationProperties(prefix = "spring.mustache")
public class MustacheConfig extends AbstractTemplateViewResolverProperties {

	private static final Log LOGGER = LogFactory.getLog(MustacheConfig.class);

	public static final String DEFAULT_PREFIX = "classpath:/templates/";

	public static final String DEFAULT_SUFFIX = ".html";

	/**
	 * Prefix to apply to template names.
	 */
	private String prefix = DEFAULT_PREFIX;

	/**
	 * Suffix to apply to template names.
	 */
	private String suffix = DEFAULT_SUFFIX;

	@Override
	public String getPrefix() {
		return this.prefix;
	}

	@Override
	public void setPrefix(String prefix) {
		this.prefix = prefix;
	}

	@Override
	public String getSuffix() {
		return this.suffix;
	}

	@Override
	public void setSuffix(String suffix) {
		this.suffix = suffix;
	}

	private final Environment environment;

	private final ApplicationContext applicationContext;

	public MustacheConfig(Environment environment, ApplicationContext applicationContext) {
		super(DEFAULT_PREFIX, DEFAULT_SUFFIX);
		this.environment = environment;
		this.applicationContext = applicationContext;
	}

	@PostConstruct
	public void checkTemplateLocationExists() {
		if (this.isCheckTemplateLocation()) {
			TemplateLocation location = new TemplateLocation(getPrefix());
			if (!location.exists(this.applicationContext)) {
				LOGGER.warn("Cannot find template location: " + location
						+ " (please add some templates, check your Mustache " + "configuration, or set spring.mustache."
						+ "check-template-location=false)");
			}
		}
	}

	@Bean
	@ConditionalOnMissingBean(Mustache.Compiler.class)
	public Mustache.Compiler mustacheCompiler(TemplateLoader mustacheTemplateLoader) {
		return Mustache.compiler().withFormatter(new Mustache.Formatter() {
			protected DateFormat _fmt = new SimpleDateFormat("yyyy-MM-dd");

			/* (non-Javadoc)
			 * @see com.samskivert.mustache.Mustache.Formatter#format(java.lang.Object)
			 */
			public String format(Object value) {
				if (value instanceof Date) {
					return _fmt.format((Date) value);
				} else if (value instanceof LocalDate) {
					return ((LocalDate) value).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
				} else if (value instanceof LocalDateTime) {
					return ((LocalDateTime) value).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
				}else if (value instanceof DateTime) {
					return BaseUtil.dateTime2String((DateTime) value,"yyyy-MM-dd");
				}
//				else if (value instanceof Double) {
//					DecimalFormat df = new DecimalFormat("#0.00"); 
//					return df.format((Double)value);
//				}else if (value instanceof BigDecimal) {
//					DecimalFormat df = new DecimalFormat("#0.0000"); 
//					return df.format((BigDecimal)value);
//				} 
				else {
					try {
						String _value = String.valueOf(value);
						_value = _value.replaceAll(" ", "%20");
						_value= URLEncoder.encode(_value, "GBK");
						_value= _value.replaceAll("%2520", " ");
						return _value;
					} catch (UnsupportedEncodingException e) {
						e.printStackTrace();
					}
					return String.valueOf(value);
				}

			}
		}).nullValue("").withLoader(mustacheTemplateLoader).withCollector(collector());
	}

	private Collector collector() {
		MustacheEnvironmentCollector collector = new MustacheEnvironmentCollector();
		collector.setEnvironment(this.environment);
		return collector;
	}

	@Bean
	@ConditionalOnMissingBean(TemplateLoader.class)
	public MustacheResourceTemplateLoader mustacheTemplateLoader() {
		MustacheResourceTemplateLoader loader = new MustacheResourceTemplateLoader(getPrefix(), getSuffix());
		loader.setCharset(getCharsetName());
		return loader;
	}

}
